package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.dto.GoodsSalesDTO;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.Orders;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.UserMapper;
import com.sky.properties.JwtProperties;
import com.sky.properties.WeChatProperties;
import com.sky.service.ReportService;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.JwtUtil;
import com.sky.vo.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private UserMapper userMapper;


    /**
     * 营业额统计接口
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //1- 根据起始日期获取到该区间的所有的日期；
        List<LocalDate> dateList = getDateList(begin, end);
        //2-依据日期分组查到每天的营业额，并将查询到的所有数据存放到List集合中；
        Map params = new HashMap<>();
        params.put("beginDate", begin);
        params.put("endDate", end);
        params.put("status", Orders.COMPLETED);
        List<Map> turmMapList = ordersMapper.groupByAmountandStatus(params);
        //2.1- 将list转为map
        Map<String, BigDecimal> turnovermap = turmMapList.stream().collect(Collectors.toMap(o -> (String) o.get("date"), o -> (BigDecimal) o.get("amount")));
        //3-将集合按照要求拼接并返还
        List<BigDecimal> turnoverlist = new ArrayList<>();
        for (LocalDate date : dateList) {
            BigDecimal amount = turnovermap.get(date.toString());
            amount = ObjectUtils.isEmpty(amount) ? BigDecimal.valueOf(0.0) : amount;
            turnoverlist.add(amount);
        }
        //4- 将集合转为字符串
        String dateListStr = StringUtils.join(dateList, ",");
        String turnoverListStr = StringUtils.join(turnoverlist, ",");
        return TurnoverReportVO.builder()
                .dateList(dateListStr)
                .turnoverList(turnoverListStr)
                .build();
    }

    /**
     * 用户数量统计接口
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //1- 根据起始日期获取到该区间的所有的日期；
        List<LocalDate> dateList = getDateList(begin, end);
        //2-将需要传入的参数封装到map集合中
        Map params = new HashMap();
        params.put("beginDate", begin);
        params.put("endDate", end);
        //3-分组查询每日新增用户数量（高效减少磁盘Io次数）
        List<Map> userMapList = userMapper.groupCountUserByparams(params);
        //3.1将list集合转为map集合 时间为键  数量为值
        Map<String, Long> userMap = userMapList.stream().collect(Collectors.toMap(u -> (String) u.get("date"), u -> (Long) u.get("num")));

        //4-查询截至到当天之前的所有用户的总数量
        params.put("date", begin.minusDays(1));
        params.put("newUserflag", false);
        Integer alluser = userMapper.countUserByparams(params);
        //5-当天之后的用户总数为 当天之前的用户量 + 当天增长的用户量
        List<Integer> totalUserList = new ArrayList<>();
        List<Long> newUserList = new ArrayList<>();
        for (LocalDate date : dateList) {
            Long newUserCount = userMap.get(date.toString());
            newUserCount = newUserCount == null ? 0 : newUserCount;
            newUserList.add(newUserCount);
            alluser += newUserCount.intValue();
            totalUserList.add(alluser);
        }
        //5- 将集合转为字符串
        String detaList = StringUtils.join(dateList, ",");
        String totalUserlist = StringUtils.join(totalUserList, ",");
        String newUserlist = StringUtils.join(newUserList, ",");
        //6-封装并返回数据
        return UserReportVO.builder()
                .dateList(detaList)
                .newUserList(newUserlist)
                .totalUserList(totalUserlist)
                .build();
    }

    /**
     * 订单统计接口
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        //1- 根据起始日期获取到该区间的所有的日期；
        List<LocalDate> dateList = getDateList(begin, end);
        //1.1-将需要传入的参数放入map集合中
        Map params = new HashMap<>();
        params.put("beginDate", begin);
        params.put("endDate", end);
        //2-获取订单总数
        List<Map> totalOrderlist = ordersMapper.groupCountOrderByparams(params);
        Map<String, Long> totalOrderMap = totalOrderlist.stream().collect(Collectors.toMap(o -> (String) o.get("date"), o -> (Long) o.get("num")));
        //3-获取有效订单数
        params.put("status", Orders.COMPLETED);
        List<Map> validOrderlist = ordersMapper.groupCountOrderByparams(params);
        Map<String, Long> validOrderMap = validOrderlist.stream().collect(Collectors.toMap(o -> (String) o.get("date"), o -> (Long) o.get("num")));
        List<Long> orderCountList = new ArrayList<>();
        List<Long> validOrderCountList = new ArrayList<>();
        for (LocalDate date : dateList) {
            //获取当天的订单总数
            Long TotalCountOrder = totalOrderMap.get(date.toString());
            TotalCountOrder = TotalCountOrder == null ? 0 : TotalCountOrder;
            orderCountList.add(TotalCountOrder);
            //获取当天有效订单的数量
            Long validCountOrder = validOrderMap.get(date.toString());
            validCountOrder = validCountOrder == null ? 0 : validCountOrder;
            validOrderCountList.add(validCountOrder);
        }
        //4-统计日期区间内的订单总数和有效订单数；
        Long orederSum = orderCountList.stream().mapToLong(on -> on).sum();
        Long validOrderSum = validOrderCountList.stream().mapToLong(on -> on).sum();
        //5-获取订单完成率
        Double orderCompletionRate = orederSum == 0 ? 0.0 : validOrderSum.doubleValue() / orederSum;

        //6-封装数据并返回
        return OrderReportVO.builder()
                .orderCompletionRate(orderCompletionRate)
                .totalOrderCount(orederSum.intValue())
                .validOrderCount(validOrderSum.intValue())
                .orderCountList(StringUtils.join(orderCountList, ","))
                .validOrderCountList(StringUtils.join(validOrderCountList, ","))
                .dateList(StringUtils.join(dateList, ","))
                .build();

    }

    /**
     * 查询销量排名前十的菜品或套餐数量
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        //1- 根据菜品或者套餐的名称分组查寻销量前十的菜品或者套餐
        Map params = new HashMap<>();
        params.put("beginDate", begin);
        params.put("endDate", end);
        params.put("status", Orders.COMPLETED);
        List<GoodsSalesDTO> goodsSalesDTOList = ordersMapper.groupBySumNumber(params);
        String namelist = goodsSalesDTOList.stream().map(g -> g.getName()).collect(Collectors.joining(","));
        String numberlist = goodsSalesDTOList.stream().map(g -> g.getNumber().toString()).collect(Collectors.joining(","));
        return SalesTop10ReportVO.builder()
                .nameList(namelist)
                .numberList(numberlist)
                .build();
    }

    /**
     * 根据起始时间获取该区间的所有日期数
     *
     * @param begin
     * @param end
     * @return
     */
    private List<LocalDate> getDateList(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        while (!begin.isEqual(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        return dateList;
    }

}
